package com.youdianstar.app.ui

import android.content.Intent
import android.os.Build
import android.view.View
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt

import com.youdianstar.app.R
import com.youdianstar.app.BR
import com.youdianstar.app.BuildConfig
import com.youdianstar.app.databinding.ActivitySettingBinding
import com.youdianstar.app.entity.TouchIDSys
import com.youdianstar.app.ui.account.LoginActivity
import com.youdianstar.app.ui.web.WebActivity
import com.youdianstar.app.ui.account.CancelActivity
import com.youdianstar.app.util.DataAppManager
import com.youdianstar.app.util.AppDialogUtil
import com.youdianstar.app.util.biometric.BiometricPopUtil
import com.youdianstar.app.util.biometric.CryptographyHelper
import com.youdianstar.app.util.biometric.IBiometricPopListener
import com.youdianstar.app.common.base.BaseActivity
import com.youdianstar.app.common.entity.BusEntity
import com.youdianstar.app.common.entity.LanguageEntity
import com.youdianstar.app.common.ex.setThrottleListener
import com.youdianstar.app.common.network.BaseApiResultObserver
import com.youdianstar.app.common.util.*
import com.youdianstar.app.common.*
import com.youdianstar.app.common.HTTP_BRS_URL
import com.youdianstar.app.common.widget.SwitchButton
import com.youdianstar.app.common.auko.startActivity
import com.safframework.eventbus.EventBus
import org.koin.androidx.viewmodel.ext.android.viewModel
import java.util.*
import javax.crypto.Cipher


/**
 * File: SettingActivity
 * Author: 82149 Create: 2021/10/26 12:09
 * Changes (from 2021/10/26)
 * --------------------------------------------------
 * description:
 * ---------------------------------------------------
 *
 */
class SettingActivity : BaseActivity<ActivitySettingBinding, SettingViewModel>() {
    override fun layoutId(): Int = R.layout.activity_setting

    override fun initVariableId(): Int = BR.viewModel

    override fun initViewModel(): SettingViewModel {
        val model: SettingViewModel by viewModel()
        return model
    }

    private var selectCode: String = ""
    private var languageList: List<LanguageEntity>? = null
    var selectIndex: Int = 0

    var accountPlain = ""
    private val bioHelper : CryptographyHelper = CryptographyHelper.getInstance()

    override fun initData() {
        super.initData()
        mBinding.headBar.initTitle(this, getString(R.string.set_setting), showInner = true)
        mBinding.tvVersion.text = "V " + BuildConfig.VERSION_NAME

        EventBus.post(BusEntity(DataCode.CLOSE_DRAWER))//关闭侧边栏
        initLanguage()
        //Touch Id
        initBiometric()
    }

    override fun initLiveObserver() {
        super.initLiveObserver()
        // 退出登录接口已废弃，不再需要观察logoutLiveData
        // mViewModel.logoutLiveData.observe(this, object : BaseApiResultObserver<Any>(true) {
        //     override fun onDataResult(data: Any?) {
        //         super.onDataResult(data)
        //         EventBus.post(BusEntity(DataCode.CLOSE_DRAWER))
        //         DataAppManager.instance.clearUserWithCookies()
        //         startActivity<LoginActivity>()
        //         finish()
        //     }
        //
        //     override fun onNetError(code: Int, e: String?) {
        //         super.onNetError(code, e)
        //         EventBus.post(BusEntity(DataCode.CLOSE_DRAWER))
        //         DataAppManager.instance.clearUserWithCookies()
        //         startActivity<LoginActivity>()
        //         finish()
        //     }
        // })

        // 注释掉语言切换网络请求的观察者，因为不再使用网络请求
        /*
        mViewModel.switchLiveData.observe(this, object : BaseApiResultObserver<Any>(true) {
            override fun onDataResult(data: Any?) {
                super.onDataResult(data)
                dismissDialog()
                switchStartHome()
            }

            override fun onNetError(code: Int, e: String?) {
                super.onNetError(code, e)
                dismissDialog()
                // 即使网络请求失败，也要重启应用应用语言设置
                switchStartHome()
                toastShow(e)
            }
        })
        */

        mViewModel.touchIdResultLiveData.observe(this, object : BaseApiResultObserver<Any>(true) {
            override fun onDataResult(data: Any?) {
                super.onDataResult(data)
                dismissDialog()
            }

            override fun onNetError(code: Int, e: String?) {
                super.onNetError(code, e)
                dismissDialog()
                toastShow(e)
            }
        })
    }

    override fun initClickEvent() {
        mBinding.rlLanguage.setThrottleListener {
            showSwitchDialog()
        }

        mBinding.lgTerms.setThrottleListener {
            val langParam = getAgreementLangParam()
            val termsUrl = "${HTTP_BRS_URL}/sw/app/agreement/user.html?lang=$langParam"
            startActivity<WebActivity>(
                Extra.IT_DATA to termsUrl, Extra.IT_NOTIFY to getString(R.string.login_termOfUse)
            )
        }

        mBinding.lgPrivacy.setThrottleListener {
            val langParam = getAgreementLangParam()
            val policyUrl = "${HTTP_BRS_URL}/sw/app/agreement/privacy.html?lang=$langParam"
            startActivity<WebActivity>(
                Extra.IT_DATA to policyUrl,
                Extra.IT_NOTIFY to getString(R.string.login_privacyPolice)
            )
        }

        mBinding.lgAccountCancel.setThrottleListener {
            startActivity<CancelActivity>()
        }

        mBinding.btnSubmit.setThrottleListener {
            showLogoutDialog()
        }
    }


    private fun showLogoutDialog() {
        AppDialogUtil.instance.showNotifyDialog(this,
            getString(R.string.set_logout), getString(R.string.set_confirmLogout),
            leftAction = {

            },
            rightAction = {
                // 退出登录接口已废弃，直接清空本地数据
                EventBus.post(BusEntity(DataCode.CLOSE_DRAWER))
                DataAppManager.instance.clearUserWithCookies()
                startActivity<LoginActivity>()
                finish()
            },
            left = getString(R.string.public_cancel),
            right = getString(R.string.public_confirm)
        )
    }


    private fun showSwitchDialog() {
        val list = mutableListOf<String>()
        languageList?.let { lanList ->
            for ((i,item) in lanList.withIndex()){
                list.add(item.language)
            }
        }
        AppDialogUtil.instance.showBoxSelectDialog(this@SettingActivity,
            getString(R.string.set_selectLanguage), list, defaultP = selectIndex
        ) {
            selectIndex = it
            languageList?.let { list ->
                switchLanguage(list[selectIndex].languageCode)
            }
        }
    }

    private fun initLanguage() {
        // TODO: 测试阶段 - 语言切换只保留三个语言：越南语、中文、英文
        // 越南语放在第一位，其他语言已注释
        languageList = listOf(
            LanguageEntity(Language.VI, getString(R.string.Set_language_VI)),
            LanguageEntity(Language.ZH, getString(R.string.Set_language_CH)),
            LanguageEntity(Language.EN, getString(R.string.Set_language_EN))
            // LanguageEntity(Language.ES, getString(R.string.Set_language_ES)), // 西班牙语已注释
        )
        val localLan = LanguageConfig.instance.getLanguageCode()
        for ((index, lan) in languageList!!.withIndex()) {
            if (lan.languageCode.lowercase(Locale.ROOT) == localLan) {
                selectIndex = index
                mBinding.tvLanguage.text = lan.language
            }
        }
    }

    private fun switchLanguage(code: String) {
        selectCode = code
        // 直接保存语言设置，不需要网络请求
        LanguageConfig.instance.saveLanguageCode(code)
        // 注释掉网络请求，直接重启应用应用语言设置
        // mViewModel.languageSwitch(code.uppercase(Locale.ROOT))
        switchStartHome()
    }

    private fun switchStartHome() {
        // 语言设置已经在switchLanguage中保存，这里只需要重启应用
        val intent = Intent(this, MainActivity::class.java)
        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
        startActivity(intent)
        finish()
    }

    private fun initBiometric(){
        val isEnableBio = BiometricManager.from(applicationContext).canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG) == BiometricManager.BIOMETRIC_SUCCESS
        mBinding.lgTouchId.visibility = if (isEnableBio) View.VISIBLE else View.GONE
        if (!isEnableBio)
            return
        DataAppManager.instance.getAccount()?.let { account ->
            accountPlain= account.getAuthAccount()
        }
        //判断加密缓存与账号缓存
        val wrapperCache: CryptographyHelper.CipherTextWrapper? = bioHelper.getCipherTextWrapper(applicationContext)
        val isSetBioAccount: Boolean = DataAppManager.instance.getNotifyFingerprint(accountPlain)
        mBinding.swcFinger.isChecked = (wrapperCache!=null && isSetBioAccount)
        mBinding.swcFinger.setOnCheckedChangeListener(object : SwitchButton.OnCheckedChangeListener {
            override fun onCheckedChanged(view: SwitchButton?, isChecked: Boolean) {
                if (isChecked) {
                    showBiometricPromptForEncryption()
                } else {
                    bioHelper.cleanCipherTextWrapper(applicationContext)
                    DataAppManager.instance.setNotifyFingerprint(accountPlain, isSave = false)
                    //同步接口
                    val token = DataAppManager.instance.getToken()
                    mViewModel.accountTouchIdSys(TouchIDSys(0,token))
                }
            }
        })
    }

    private fun showBiometricPromptForEncryption() {
        val cipher: Cipher? = bioHelper.getInitCipherForEncryption(CryptographyHelper.BIOMETRIC_KEY)
        if (cipher == null) {
            toastShow("TouchId Data Error!")
            mBinding.swcFinger.isChecked = false
            return
        }
        val prompt: BiometricPrompt = BiometricPopUtil.createBiometricPrompt(this, object : IBiometricPopListener {

            override fun onAuthSuccess(result: BiometricPrompt.AuthenticationResult) {
                if (null != result.cryptoObject && null != result.cryptoObject!!.cipher) {
                    val cipherData = result.cryptoObject!!.cipher
                    val tokenWrapper: CryptographyHelper.CipherTextWrapper? = bioHelper.encryptData(DataCode.TOUCH_ID_KEY, cipherData!!)
                    tokenWrapper?.let { wrapper ->
                        bioHelper.persistCipherTextWrapper(wrapper, applicationContext)

                        //更新缓存token
                        DataAppManager.instance.getAccount()?.let { account ->
                            val cachePlain = account.getAuthAccount()
                            val token = DataAppManager.instance.getToken()
                            DataAppManager.instance.setNotifyFingerprint(cachePlain, token, isSave = true)

                            mViewModel.accountTouchIdSys(TouchIDSys(state = 1,token))
                        }
                    }
                } else {
                    toastShow("TouchId Data Error!")
                }
            }

            override fun onAuthFailed(reason: String?) {
                if (!StrUtil.isEmpty(reason))
                    toastShow(reason)
                mBinding.swcFinger.isChecked = false
            }
        })

        val promptInfo: BiometricPrompt.PromptInfo = BiometricPopUtil.createPromptInfo(this)
        prompt.authenticate(promptInfo, BiometricPrompt.CryptoObject(cipher))
    }

    /**
     * 获取协议语言参数
     * 规则：中文(zh) -> cn，其他语言 -> vi（默认）
     */
    private fun getAgreementLangParam(): String {
        val languageCode = LanguageConfig.instance.getLanguageCode()
        return if (languageCode == Language.ZH) "cn" else "vi"
    }

}